import type { Equal, IsFalse, IsTrue } from '../../../util-types/index'

// 
type DeepObjectToUniq<O extends object> = {
    [k in keyof O]: O[k] extends object ? DeepObjectToUniq<O[k]> & { [unique: symbol]: [O, k] } : O[k]
} & { [unique: symbol]: O }

type Quz = { quz: 4 }

type Foo = { foo: 2; baz: Quz; bar: Quz }
type Bar = { foo: 2; baz: Quz; bar: Quz & { quzz?: 0 } }



type UniqQuz = DeepObjectToUniq<Quz>
type UniqFoo = DeepObjectToUniq<Foo>
type UniqBar = DeepObjectToUniq<Bar>

declare let foo: Foo
declare let uniqFoo: UniqFoo

uniqFoo = foo
foo = uniqFoo

type cases = [
    IsFalse<Equal<UniqQuz, Quz>>,
    IsFalse<Equal<UniqFoo, Foo>>,
    IsTrue<Equal<UniqFoo['foo'], Foo['foo']>>,
    IsTrue<Equal<UniqFoo['bar']['quz'], Foo['bar']['quz']>>,
    IsFalse<Equal<UniqQuz, UniqFoo['baz']>>,
    IsFalse<Equal<UniqFoo['bar'], UniqFoo['baz']>>,
    IsFalse<Equal<UniqBar['baz'], UniqFoo['baz']>>,
    IsTrue<Equal<keyof UniqBar['baz'], keyof UniqFoo['baz']>>,
    IsTrue<Equal<keyof Foo, keyof UniqFoo & string>>,
]